package com.zhangmeng.tools.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.StreamProgress;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import com.zhangmeng.tools.utils.AlertUtils;
import javafx.application.Platform;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author : 芊芊墨客
 * @version : 1.0
 * @date : 2023-03-08 12:01
 */
@Slf4j
public class HttpDownLoadController {

    @FXML
    public ProgressBar progress;

    @FXML
    public TextField url;

    @FXML
    public Button download;

    @FXML
    public TextArea download_info;

    @FXML
    private TextField download_path;

    @FXML
    private Button choose_file;

    private final SimpleObjectProperty<File> file_target = new SimpleObjectProperty<>();

    private static final int DEFAULT_BUFFER_SIZE = 8192;

    @FXML
    public void initialize() {

        choose_file.setOnAction(event -> {
            Stage stage = new Stage();
            DirectoryChooser dc = new DirectoryChooser();
            dc.setTitle("文件夹选择器");
            File file = dc.showDialog(stage);
            if (file != null){
                download_path.setText(file.getPath());
                file_target.setValue(file);
            }
        });

        download.setOnAction(event -> {

            if (url.getText().length() == 0 ){
                AlertUtils.alert_warning("请输入下载文件的地址再试!");
                return;
            }

            if (download_path.getText().length() == 0){
                AlertUtils.alert_warning("请输入文件保存地址再试!");
                return;
            }

            download_info.setText(null);

            MyService myService = new MyService();
            myService.progressProperty().addListener((observable, oldValue, newValue) -> {
                if (newValue.doubleValue() >= 1){
                    myService.cancel();
                    log.info("任务取消!.......");
                }else {
                    progress.setProgress(newValue.doubleValue());
                }
            });

            myService.messageProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
                    if(newValue != null){
                        download_info.appendText(newValue);
                        download_info.appendText(System.lineSeparator());
                    }
                }
            });
            myService.start();
        });
    }

    class  MyService extends Service<Number>{

        @Override
        protected Task<Number> createTask() {
            return new Task<>() {
                @Override
                protected Number call() {
                    int size = 0;
                    try {
                        URL url1 = new URL(url.getText());
                        URLConnection conn = url1.openConnection();
                        size = conn.getContentLength();
                        if (size < 0) {
                            download_info.appendText("无法获取文件大小。");
                            download_info.appendText(System.lineSeparator());
                        } else {
                            download_info.appendText("文件大小为：" + FileUtil.readableFileSize(size));
                            download_info.appendText(System.lineSeparator());
                            String fileName;
                            final String path = url.getText();
                            // 从路径中获取文件名
                            fileName = StrUtil.subSuf(path, path.lastIndexOf('/') + 1);
                            if (StrUtil.isBlank(fileName)) {
                                // 编码后的路径做为文件名
                                fileName = URLUtil.encodeQuery(path, CharsetUtil.CHARSET_UTF_8);
                            }
                            String pathText = download_path.getText();
                            InputStream fis = conn.getInputStream();
                            FileOutputStream fos = new FileOutputStream(new File(pathText + "/" + fileName));
                            byte[] bytes = new byte[DEFAULT_BUFFER_SIZE];
                            int i;
                            double sum = 0;
                            double progress = 0;
                            this.updateMessage("开始下载:-------->" + pathText + "/" + fileName);
                            while ((i = fis.read(bytes, 0, DEFAULT_BUFFER_SIZE)) != -1) {
                                if (this.isCancelled()) {
                                    break;
                                }
                                fos.write(bytes, 0, i);
                                sum = sum + i;
                                this.updateProgress(sum, size);
                                progress = sum / size;
                                this.updateMessage("已下载:" + FileUtil.readableFileSize((long) sum));
                            }

                            fis.close();
                            fos.close();

                            this.updateMessage("下载结束:-------->" + FileUtil.readableFileSize(size));
                            return progress;
                        }
                    } catch (IOException e) {
                        download_info.appendText(e.getMessage());
                        download_info.appendText(System.lineSeparator());
                    }
                    return null;
                }
            };
        }
    }
}
